package Lab4;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

/**
 * A GUI for an RPN calculator. Requires a class implementing the interface
 * Calculations in order to work.
 * 
 * @author dale
 */
public class CalculatorFrame extends JFrame implements ActionListener {
	/** The initial size of the frame */
	public static final Dimension FRAME_SIZE = new Dimension(300, 300);
	private final int N_NUMBER_BUTTONS = 10;
	private JTextField textArea;
	private JButton[] numberButtons;
	private JPanel buttonPanel;
	private LockBrain brain;
	private int numCorrect = 0;
	private int[] code = new int[] { 0, 1, 2, 3 };

	private enum LockState {
		LOCKED, UNLOCKED
	};

	private LockState locked = LockState.LOCKED;

	/**
	 * Constructor instantiates objects and lays out the GUI
	 */
	public CalculatorFrame() {
		super("RPN Calculator");

		brain = new LockBrain();

		createGUIcomponents();

		layoutGUI();

		// If the user clicks on the window close button, exit
		this.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
	}

	/**
	 * Create GUI components and set their properties
	 */
	private void createGUIcomponents() {
		// Create the components
		textArea = new JTextField();
		buttonPanel = createButtonPanel();

		// Set properties
		textArea.setEditable(false);
	}

	/**
	 * Lay out the GUI components
	 */
	private void layoutGUI() {
		Container c = this.getContentPane();
		c.setLayout(new BorderLayout());
		c.add(textArea, BorderLayout.CENTER);
		c.add(buttonPanel, BorderLayout.SOUTH);

		// Set the default size and make the frame visible
		this.setSize(FRAME_SIZE);
		this.setPreferredSize(FRAME_SIZE);
		this.setVisible(true);
	}

	/**
	 * Create the panel containing all of the calculator buttons
	 * 
	 * @return A JPanel containing the buttons
	 */
	private JPanel createButtonPanel() {
		// Create all of the buttons and register callbacks
		numberButtons = new JButton[N_NUMBER_BUTTONS];
		for (int i = 0; i < N_NUMBER_BUTTONS; i++) {
			numberButtons[i] = new JButton(Integer.toString(i));
			numberButtons[i].addActionListener(this);
		}

		// Layout in a new panel using a GridLayout
		JPanel panel = new JPanel(new GridLayout(5, 4));
		// First row
		for (int i = 0; i < 3; i++) {
			panel.add(numberButtons[i + 1]);
		}

		// Second row
		for (int i = 3; i < 6; i++) {
			panel.add(numberButtons[i + 1]);
		}

		// Third row
		for (int i = 6; i < 9; i++) {
			panel.add(numberButtons[i + 1]);
		}

		// Fourth row
		panel.add(new JPanel());
		panel.add(numberButtons[0]);

		textArea.setText("LOCKED");

		return panel;
	}

	/**
	 * Go through the buttons the source is found and then take appropriate
	 * action
	 * 
	 * @param ev
	 *            The event from a button
	 */
	public void actionPerformed(ActionEvent ev) {
		for (int i = 0; i < numberButtons.length; i++) {
			if (ev.getSource() == numberButtons[i]) {
				stateMachine(i);
				return;
			}
		}
	}

	/**
	 * Receives code inputs from the GUI, and processes them,
	 * checks if they're correct, then increments numCorrect if the number is
	 * correct. Resets the counter if the number is not correct.
	 * 
	 * Also shifts state when the desired code is entered by the user.
	 * 
	 * @param i
	 *            - The code number from the button currently pressed by the
	 *            user.
	 */
	private void stateMachine(int i) {
		switch (locked) {

		// We'll hit this case if the program sees that
		// numCorrect is equal to 4. This means they got the code right.
		case UNLOCKED:
			numCorrect = 0;
			textArea.setText("LOCKED");
			locked = LockState.LOCKED;

			// Default case. Assume the code has not been entered,
			// or has not been entered correctly. Does all the work
			// of checking the code being entered. Increments
			// numCorrect if it sees the right code number being entered.
		case LOCKED:
			if (i == code[numCorrect]) {
				numCorrect++;
			} else {
				numCorrect = 0;
			}

			if (numCorrect == 4) {
				textArea.setText("UNLOCKED");
				locked = LockState.UNLOCKED;
			}

			break;
		}
	}

	/**
	 * Just instantiates the class
	 * 
	 * @param args
	 *            Ignored
	 */
	public static void main(String[] args) {
		new CalculatorFrame();
	}
}